package com.venutech.gongan.util;

import java.awt.geom.Point2D;
import java.util.List;

/**
 * @ClassName: regionUtil
 * @Author: liuzhengli
 * @Description: TODO 判断设备是否在划定的区域内的工具类
 * @Date: 2021/9/2 0002 13:17
 * @Version: 1.0
 */
public class regionUtil {
    private static double EARTH_RADIUS = 6378137;
//private static double EARTH_SEA = 1.852;海里

    /**
     2     * 是否在矩形区域内
     3     * @Title: isInArea
     4     * @Description: TODO()
     5     * @param lat 测试点经度
     6     * @param lng 测试点纬度
     7     * @param minLat 纬度范围限制1
     8     * @param minLng 经度限制范围1
     9     * @param maxLat 纬度范围限制2
     10     * @param maxLng 经度范围限制2
     11     * @return
     12     * @return boolean
     13     * @throws
     14     */
    /**
     临时用户管理的区域:{
     left_top_longitude=120.6063511554,
     left_top_latitude=31.3324730576,
     right_bottom_longitude=120.606753989,
     right_bottom_latitude=31.3326195425
     }

     31.3324547469
     120.6064610191
     */
    public static boolean isInRectangleArea(double lat,double lng,double left_top_lat,double left_top_lng, double right_bottom_lat,double right_bottom_lng){
        if(isInRange(lat, right_bottom_lat, left_top_lat)){//如果在纬度的范围内
            if(right_bottom_lng*left_top_lng>0){ //如果在纬度的范围内
                if(isInRange(lng, right_bottom_lng, left_top_lng)){ //如果在经度的范围内
                    return true;
                }else {
                    return false;
                }
            }else {
                if(Math.abs(right_bottom_lng)+Math.abs(left_top_lng)<180){
                    if(isInRange(lng, right_bottom_lng, left_top_lng)){
                        return true;
                    }else {
                        return false;
                    }
                }else{
                    double left = Math.max(right_bottom_lng, left_top_lng);
                    double right = Math.min(right_bottom_lng, left_top_lng);
                    if(isInRange(lng, left, 180)||isInRange(lng, right,-180)){
                        return true;
                    }else {
                        return false;
                    }
                }
            }
        }else{
            return false;
        }

    }

    /**
     *  目标点是否在目标边上边上<br/>
     *
     * @param px0 目标点的经度坐标
     * @param py0 目标点的纬度坐标
     * @param px1 目标线的起点(终点)经度坐标
     * @param py1 目标线的起点(终点)纬度坐标
     * @param px2 目标线的终点(起点)经度坐标
     * @param py2 目标线的终点(起点)纬度坐标
     * @return
     */
    public static boolean isPointOnLine(double px0, double py0, double px1, double py1, double px2, double py2)
    {
        boolean flag = false;
        double ESP = 1e-9;//无限小的正数
        if ( (Math.abs(Multiply(px0, py0, px1, py1, px2, py2)) < ESP) && ((px0 - px1) * (px0 - px2) <= 0)
                && ((py0 - py1) * (py0 - py2) <= 0) )
        {
            flag = true;
        }
        return flag;
    }
    public static double Multiply ( double px0 , double py0 , double px1 , double py1 , double px2 , double py2 )
    {
        return ((px1 - px0) * (py2 - py0) - (px2 - px0) * (py1 - py0));
    }


    /**
     2     * 判断点是否在多边形内
     3     * @Title: IsPointInPoly
     4     * @Description: TODO()
     5     * @param point 测试点
     6     * @param pts 多边形的点
     7     * @return
     8     * @return boolean
     9     * @throws
     10     */
  public static boolean isInPolygon(Point2D.Double point, List<Point2D.Double> pts){

                 int N = pts.size();
                 boolean boundOrVertex = true;
                 int intersectCount = 0;//交叉点数量
                 double precision = 2e-10; //浮点类型计算时候与0比较时候的容差
                 Point2D.Double p1, p2;//临近顶点
                 Point2D.Double p = point; //当前点

                 p1 = pts.get(0);
                 for(int i = 1; i <= N; ++i){
                         if(p.equals(p1)){
                                 return boundOrVertex;
                             }

                         p2 = pts.get(i % N);
                         if(p.x < Math.min(p1.x, p2.x) || p.x > Math.max(p1.x, p2.x)){
                                 p1 = p2;
                                 continue;
                             }

                         //射线穿过算法
                         if(p.x > Math.min(p1.x, p2.x) && p.x < Math.max(p1.x, p2.x)){
                                 if(p.y <= Math.max(p1.y, p2.y)){
                                         if(p1.x == p2.x && p.y >= Math.min(p1.y, p2.y)){
                                                 return boundOrVertex;
                                             }

                                         if(p1.y == p2.y){
                                                 if(p1.y == p.y){
                                                         return boundOrVertex;
                                                     }else{
                                                         ++intersectCount;
                                                     }
                                             }else{
                                                 double xinters = (p.x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x) + p1.y;
                                                 if(Math.abs(p.y - xinters) < precision){
                                                         return boundOrVertex;
                                                     }

                                                 if(p.y < xinters){
                                                         ++intersectCount;
                                                     }
                                             }
                                     }
                             }else{
                                 if(p.x == p2.x && p.y <= p2.y){
                                         Point2D.Double p3 = pts.get((i+1) % N);
                                         if(p.x >= Math.min(p1.x, p3.x) && p.x <= Math.max(p1.x, p3.x)){
                                                 ++intersectCount;
                                             }else{
                                                 intersectCount += 2;
                                             }
                                     }
                             }
                         p1 = p2;
                     }
                 if(intersectCount % 2 == 0){//偶数在多边形外
                         return false;
                     } else { //奇数在多边形内
                         return true;
                     }
             }

    /**
     2     * 判断是否在经纬度范围内
     3     * @Title: isInRange
     4     * @Description: TODO()
     5     * @param point
     6     * @param left
     7     * @param right
     8     * @return
     9     * @return boolean
     10     * @throws
     11     */
    public static boolean isInRange(double point, double left,double right){
        System.err.println(point+"-----------"+left+"---------------------"+right);
        if(point>=Math.min(left, right)&&point<=Math.max(left, right)){
            return true;
        }else {
            return false;
        }
    }

}
